﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace InfoPick.Lib.Tools
{
    public abstract class StringTools
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="str"></param>
        /// <param name="startIdentifier">开始标记</param>
        /// <param name="endIdentifier">结束标记</param>
        /// <param name="startIdentifier">子字符串是否包含开始标记</param>
        /// <param name="endIdentifier">子字符串是否包含结束标记</param>
        /// <returns>子字符串</returns>
        public static string AdvSubString(string str, string startIdentifier, string endIdentifier, int startIdx,
            bool identityStartInc = false, bool identityEndInc = false)
        {
            int start = string.IsNullOrEmpty(startIdentifier) ? 0 : str.IndexOf(startIdentifier, startIdx);
            int end = string.IsNullOrEmpty(endIdentifier) ? str.Length : str.IndexOf(endIdentifier, startIdx);

            //找出比start大的第一个endIdentifier位置
            while (end != -1 && end < (start + startIdentifier.Length))
                end = str.IndexOf(endIdentifier, end + endIdentifier.Length);

            if (start == -1 || end == -1)
                return string.Empty;

            if (!identityStartInc)
                start += startIdentifier.Length;
            if (identityEndInc)
                end += endIdentifier.Length;

            return str.Substring(start, end - start);
        }

        /// <summary>
        /// 字符串筛选
        /// </summary>
        /// <param name="str">输入</param>
        /// <param name="startIdentifier">开始标记</param>
        /// <param name="endIdentifier">结束标记</param>
        /// <param name="startWith">每一行除去空格后，以此字符串开始</param>
        /// <returns></returns>
        public static string[] StrFilter(string str, string startIdentifier, string endIdentifier, int startIdx,
            string[] split, string startWith = null, char[] trim = null)
        {
            string subStr = AdvSubString(str, startIdentifier, endIdentifier, startIdx);

            if (trim != null)
                subStr = subStr.Trim(trim);

            var table = subStr.Split(split, StringSplitOptions.RemoveEmptyEntries).Where(c => !string.IsNullOrWhiteSpace(c));

            if (string.IsNullOrEmpty(startWith))
                return table.ToArray();
            else
                return table.Where(c => c.Trim().StartsWith(startWith)).ToArray();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="str"></param>
        /// <param name="startIdentifier">开始标记</param>
        /// <param name="endIdentifier">结束标记</param>
        /// <param name="startIdentifier">子字符串是否包含开始标记</param>
        /// <param name="endIdentifier">子字符串是否包含结束标记</param>
        /// <returns>子字符串</returns>
        public static string AdvSubString(string str, string startIdentifier, string []endIdentifier, int startIdx,
             bool identityStartInc = false, bool identityEndInc = false)
        {
            int start = string.IsNullOrEmpty(startIdentifier) ? 0 : str.IndexOf(startIdentifier,startIdx);
            string firstEndIdentifier = endIdentifier[0];
            if (string.IsNullOrEmpty(firstEndIdentifier))
                throw new Exception("结束标记格式错误，结束标记第一个值不能为空");
            int end = str.IndexOf(firstEndIdentifier, startIdx);

            //找出比start大的第一个endIdentifier位置
            while (end != -1 && end < (start + startIdentifier.Length))
                end = str.IndexOf(firstEndIdentifier, end + endIdentifier.Length);

            if (start == -1 || end == -1)
                return string.Empty;

            if (CheckIsComplete(str, endIdentifier, ref end, end))
            {
                if (!identityStartInc)
                    start += startIdentifier.Length;
                if (identityEndInc)
                    end += endIdentifier[endIdentifier.Length - 1].Length;
                return str.Substring(start, end - start);
            }
            else
            {
                return string.Empty;
            }
        }

        /// <summary>
        /// 字符串筛选
        /// </summary>
        /// <param name="str">输入</param>
        /// <param name="startIdentifier">开始标记</param>
        /// <param name="endIdentifier">结束标记</param>
        /// <param name="startWith">每一行除去空格后，以此字符串开始</param>
        /// <returns></returns>
        public static string[] StrFilter(string str, string startIdentifier, string []endIdentifier, int startIdx,
            string[] split, string startWith = null, char[] trim = null)
        {
            string subStr = AdvSubString(str, startIdentifier, endIdentifier, startIdx);

            if (trim != null)
                subStr = subStr.Trim(trim);

            var table = subStr.Split(split, StringSplitOptions.RemoveEmptyEntries).Where(c=>!string.IsNullOrWhiteSpace(c));

            if (string.IsNullOrEmpty(startWith))
                return table.ToArray();
            else
                return table.Where(c => c.Trim().StartsWith(startWith)).ToArray();
        }

        /// <summary>
        /// 字符串表转换成字典，表格式如下：
        ///     KEY1 分隔符  VALUE1
        ///     KEY2 分隔符  VALUE2
        /// </summary>
        /// <param name="table">字符串表</param>
        /// <param name="split">分隔符</param>
        /// <returns></returns>
        public static Dictionary<string, string> StrTable2Dict(string[] table, string[] split)
        {
            Dictionary<string, string> dict = new Dictionary<string, string>();
            foreach (var row in table)
            {
                var ary = row.Split(split, StringSplitOptions.RemoveEmptyEntries);

                if (ary.Length == 2)
                {
                    if (string.IsNullOrEmpty(ary[0].Trim()))
                    {
                        var lastItem = dict.ElementAt(dict.Count - 1);
                        string newValue = string.Format("{0},{1}", lastItem.Value, ary[1].Trim());
                        dict.Remove(lastItem.Key);
                        dict.Add(lastItem.Key, newValue);
                    }
                    else
                    {
                        dict.Add(ary[0].Trim(), ary[1].Trim());
                    }
                }
            }

            return dict;
        }

        /// <summary>
        /// 根据filter查找str中包含filter的行
        /// </summary>
        /// <param name="str"></param>
        /// <param name="filter"></param>
        /// <returns></returns>
        public static string GetFilterRow(string str, string filter, ref int idx)
        {
            idx = str.IndexOf(filter, idx);

            if (idx == -1)
                return string.Empty;

            //找出包含filte的行的起始位置和结束位置
            int rowStartIdx = 0;
            int rowEndIdx = 0;
            const string wrap = "\r\n";
            while (rowEndIdx != -1 && rowEndIdx < idx)
            {
                rowStartIdx = rowEndIdx;
                rowEndIdx = str.IndexOf(wrap, rowEndIdx + wrap.Length);
            }
            if (rowEndIdx == -1)
                return str.Substring(rowStartIdx + 2);
            else
                return str.Substring(rowStartIdx + 2, rowEndIdx - rowStartIdx - 2);
                
        }

        /// <summary>
        /// 根据filter查找str中包含filter的行
        /// </summary>
        /// <param name="str"></param>
        /// <param name="filter"></param>
        /// <returns></returns>
        public static string GetFilterRow(string str, string filter)
        {
            int idx = 0;
            return GetFilterRow(str, filter, ref idx);

        }

        //Default Code:gb2312 位置
        public static int[] GetColIdx(string header)
        {
            var colAry = header.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
            int[] Cols = new int[colAry.Length];
            int idx = 0;
            var encoding = Encoding.GetEncoding("gb2312");
            foreach (var item in colAry)
            {
                string pre = header.Substring(0, header.IndexOf(item));
                Cols[idx++] = encoding.GetByteCount(pre);
            }
            return Cols;
        }

        public static string[][] GetTable(string str, string startIdentifier, string endIdentifier)
        {
            string subStr = AdvSubString(str, startIdentifier, endIdentifier,0);

            var ary = subStr.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries)
                .Where(c => !string.IsNullOrWhiteSpace(c)).ToArray();
            if (ary.Length > 2)
            {
                string header = ary[1];

                var cols = StringTools.GetColIdx(header);
                string[][] table = new string[ary.Length - 2][];
                var encoding = Encoding.GetEncoding("gb2312");
                for (int i = 0; i < ary.Length - 2; i++)
                {
                    table[i] = new string[cols.Length];
                    var bits = encoding.GetBytes(ary[i + 2]);
                    if (bits.Length <= cols[cols.Length - 1])
                        continue;
                    for (int j = 0; j < cols.Length; j++)
                    {
                        if (j < cols.Length - 1)
                            table[i][j] = encoding.GetString(bits, cols[j], cols[j + 1] - cols[j]).Trim();
                        else
                            table[i][j] = encoding.GetString(bits, cols[j], bits.Length - cols[j]).Trim();
                    }
                }
                return table;
            }

            return null;
        }


        /// <summary>
        /// 检测字符串是否全部读取
        /// </summary>
        /// <param name="sb"></param>
        /// <param name="endIdentifiers">结束标示符，有先后关系
        /// 数组中索引越大的标示符在返回字符串中的位置索引也越大</param>
        /// <returns></returns>
        public static bool CheckIsComplete(string sb, string[] endIdentifiers, int preIdxOf = 0)
        {
            int endIdx = 0;
            return CheckIsComplete(sb, endIdentifiers, ref endIdx, preIdxOf);
        }

        /// <summary>
        /// 监测字符串是否全部读取
        /// </summary>
        /// <param name="sb"></param>
        /// <param name="endIdentifiers">结束标示符，有先后关系
        /// 数组中索引越大的标示符在返回字符串中的位置索引也越大</param>
        /// <returns></returns>
        public static bool CheckIsComplete(string sb, string[] endIdentifiers, ref int endIdx, int preIdxOf = 0)
        {
            for (int i = 0; i < endIdentifiers.Length; i++)
            {
                if ((preIdxOf = sb.IndexOf(endIdentifiers[i], preIdxOf)) == -1)
                    break;
                preIdxOf += endIdentifiers[i].Length;
                if (i == endIdentifiers.Length - 1)
                {
                    endIdx = preIdxOf - endIdentifiers[i].Length;
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// 检查命令返回的执行编码是否为“成功”
        /// </summary>
        /// <param name="res"></param>
        /// <returns></returns>
        public static bool CheckReturnCode(string res)
        {
            string row = StringTools.GetFilterRow(res, "RETCODE");
            if (string.IsNullOrEmpty(row))
                throw new Exception(string.Format("返回信息没有找 RETCODE 信息\r\n{0}",res));
            var ary = row.Split('=');
            if (ary.Length > 1)
            {
                if (ary[1].Trim().Split(' ')[0].Trim() != "0")
                {
                    return false;
                }
            }
            else
            {
                return false;
            }
            return true;

        }


        /// 转全角的函数(SBC case)
        ///
        ///任意字符串
        ///全角字符串
        ///
        ///全角空格为12288，半角空格为32
        ///其他字符半角(33-126)与全角(65281-65374)的对应关系是：均相差65248
        ///
        public static String ToSBC(String input)
        {
            // 半角转全角：
            char[] c = input.ToCharArray();
            for (int i = 0; i < c.Length; i++)
            {
                if (c[i] == 32)
                {
                    c[i] = (char)12288;
                    continue;
                }
                if (c[i] < 127)
                    c[i] = (char)(c[i] + 65248);
            }
            return new String(c);
        }

        /**/
        // /
        // / 转半角的函数(DBC case)
        // /
        // /任意字符串
        // /半角字符串
        // /
        // /全角空格为12288，半角空格为32
        // /其他字符半角(33-126)与全角(65281-65374)的对应关系是：均相差65248
        // /
        public static String ToDBC(String input)
        {
            char[] c = input.ToCharArray();
            for (int i = 0; i < c.Length; i++)
            {
                if (c[i] == 12288)
                {
                    c[i] = (char)32;
                    continue;
                }
                if (c[i] > 65280 && c[i] < 65375)
                    c[i] = (char)(c[i] - 65248);
            }
            return new String(c);
        }
    }

}
